package com.hqd.ch03.v20.aop.interceptor;

import com.hqd.ch03.v20.aop.Advisor;
import com.hqd.ch03.v20.aop.support.DefaultPointcutAdvisor;
import com.hqd.ch03.v20.aopalliance.intercept.MethodInterceptor;
import com.hqd.ch03.v20.aopalliance.intercept.MethodInvocation;
import com.hqd.ch03.v20.core.Ordered;
import com.hqd.ch03.v20.thread.NamedThreadLocal;

/**
 * 默认拦截器
 * 优先级最高
 */
public class ExposeInvocationInterceptor implements MethodInterceptor, Ordered {
    public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();
    public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
        @Override
        public String toString() {
            return ExposeInvocationInterceptor.class.getName() + ".ADVISOR";
        }
    };
    private static final ThreadLocal<MethodInvocation> invocation =
            new NamedThreadLocal<>("Current AOP method invocation");

    private ExposeInvocationInterceptor() {
    }

    public static MethodInvocation currentInvocation() throws IllegalStateException {
        MethodInvocation mi = invocation.get();
        if (mi == null) {
            throw new IllegalStateException("未找到调用链，请检查工程");
        }
        return mi;
    }

    public Object invoke(MethodInvocation mi) throws Throwable {
        MethodInvocation oldInvocation = invocation.get();
        invocation.set(mi);
        try {
            return mi.proceed();
        } finally {
            invocation.set(oldInvocation);
        }
    }

    @Override
    public int getOrder() {
        return HIGHEST_PRECEDENCE + 1;
    }
}
